class Router {
  constructor(arg) {
    // 路由跳转方法映射
    this.routeMap = {
      push: 'navigateTo',
      replace: 'redirectTo',
      replaceAll: 'reLaunch',
      pushTab: 'switchTab'
    };
    this.app = null;
    if (arg && arg.constructor !== Object) {
      return console.error(`Routing configuration must be an Object`);
    }
    Router.$root = this;
  }

  /**
   * 执行路由跳转
   */
  _pushTo() {
    return new Promise((resolve, reject) => {
      let { path, params, method } = this.tempRoute;
      // 对首次进入页面执行路由守卫时如果放行，method path params都为空 此时应该直接中断流程，无需抛出异常
      if (!method && !path && !params) {
        return;
      }
      let urlParams = '?';
      if (!path) {
        reject(new Error('参数page未填写'));
        return;
      } else if (params && typeof params === 'object') {
        // 处理参数，转换为url字符串
        Object.keys(params).forEach(k => {
          // 深度对象转为json字符串（包含数组）
          if (typeof params[k] === 'object') {
            if (params[k]) {
              const json = JSON.stringify(params[k]);
              urlParams += `${k}=${json}&`;
            } else {
              urlParams += `${k}=&`;
            }
          } else if (typeof params[k] === 'number' || typeof params[k] === 'string' || typeof params[k] === 'boolean') {
            // 基础值直接写入
            urlParams += `${k}=${params[k]}&`;
          } else if (typeof params[k] === 'undefined') {
            urlParams += `${k}=&`;
          }
        });
      }

      // 参数组装
      if (urlParams.length === 1) {
        urlParams = '';
      } else {
        urlParams = urlParams.substr(0, urlParams.length - 1);
      }

      // 设置路由跳转方式
      if (!method) {
        method = 'navigateTo';
      }
      if (this.routeMap[method]) {
        method = this.routeMap[method];
      }

      // 调用系统跳转方法
      uni[method]({
        url: path + urlParams,
        success: () => {
          // 执行路由后置守卫
          if (this._afterEach && typeof this._afterEach === 'function') {
            this._afterEach.call(this, this.tempRoute, this.route);
          }
          // 更新路由信息
          this.route = {
            path: path + urlParams,
            params: params || {},
            page: path
          };
          this.tempRoute = null;
          resolve();
        },
        fail: e => {
          reject(new Error('路由跳转失败！'));
        }
      });
    });
  }

  /**动态的导航到一个新 URL 保留浏览历史
   * navigateTo
   * @param {Object} rule
   */
  push(arg) {
    const rule = {
      method: 'navigateTo'
    };
    if (typeof arg === 'string') {
      rule.path = arg;
    } else if (typeof arg === 'object') {
      rule.path = arg.path;
      rule.params = arg.params;
    }
    this.next(rule);
  }

  /**动态的导航到一个新 URL 关闭当前页面，跳转到的某个页面。
   * redirectTo
   * @param {Object} rule
   */
  replace(arg) {
    const rule = {
      method: 'redirectTo'
    };
    if (typeof arg === 'string') {
      rule.path = arg;
    } else if (typeof arg === 'object') {
      rule.path = arg.path;
      rule.params = arg.params;
    }
    this.next(rule);
  }

  /**动态的导航到一个新 URL 关闭所有页面，打开到应用内的某个页面
   *  reLaunch
   * @param {Object} rule
   */
  replaceAll(arg) {
    const rule = {
      method: 'reLaunch'
    };
    if (typeof arg === 'string') {
      rule.path = arg;
    } else if (typeof arg === 'object') {
      rule.path = arg.path;
      rule.params = arg.params;
    }
    this.next(rule);
  }

  /** 跳转Tabbar
   *  switchTab
   * @param {Object} rule
   */
  pushTab(arg) {
    const rule = {
      method: 'switchTab'
    };
    if (typeof arg === 'string') {
      rule.path = arg;
    } else if (typeof arg === 'object') {
      rule.path = arg.path;
      rule.params = arg.params;
    }
    this.next(rule);
  }

  /**
   * 返回到指定层级页面上
   */
  back(delta = 1) {
    // 返回上级
    if (delta.constructor != Number) {
      this._errorHandler(new Error('返回层级参数必须是一个Number类型且必须大于0：'));
      return;
    }
    uni.navigateBack({
      delta
    });
  }

  /**
   * 分发路由
   * @param {Object} args
   */
  _next() {
    return new Promise((resolve, reject) => {
      if (this._beforeEach && typeof this._beforeEach === 'function') {
        // 需要传给守卫 to from next
        this._beforeEach.call(this, this.tempRoute, this.route, resolve);
      } else {
        this._pushTo().catch(e => {
          reject(e);
        });
      }
    });
  }

  next(args) {
    if (args) {
      // 保存临时数据
      if (typeof args === 'object') {
        this.tempRoute = {
          // 第一次调用next一定存在method，后续循环调用可能不会存在，不存在时使用上次缓存的method
          method: args.method || this.tempRoute.method,
          path: args.page || args.path,
          params: args.params
        };
      } else if (typeof args === 'string') {
        this.tempRoute = {
          path: args
        };
      } else if (!args) {
        // 中断路由 args = false
        this.tempRoute = null;
        return;
      }

      if (!this.route) {
        this.route = {
          path: '/' + getCurrentPages()[0].route
        };
      }

      this._next()
        .then(args => {
          this.next(args);
        })
        .catch(e => {
          this.tempRoute = null;
          this._errorHandler(e);
        });
    } else {
      this._pushTo().catch(e => {
        this.tempRoute = null;
        this._errorHandler(e);
      });
    }
  }

  /**
   * 应用启动时执行一次路由检查（前置守卫，若通过则不做事情）
   */
  doBeforeHooks() {
    this.tempRoute = {};
    this.next({});
  }

  // 设置路由前置/后置守卫
  beforeEach(fn) {
    this._beforeEach = fn;
  }
  afterEach(fn) {
    this._afterEach = fn;
  }
  // 设置路由跳转错误处理
  onError(fn) {
    if (fn && typeof fn === 'function') {
      this._errorHandler = fn;
    }
  }

  // 获取当前路由信息
  getCurrentRoute() {
    return this.route;
  }

  /**
   * 返回APP数据
   * @return {[type]} [description]
   */
  setAdhibition(self) {
    this.app = self;
  }
}

// 路由对象属性定义
Router.$root = null;
// 定义VM应用
Router.app = null;
// 当前路由内容
Router.route = null;
// 临时路由信息
Router.tempRoute = null;
// 路由前置后置守卫
Router._beforeEach = null;
Router._afterEach = null;
// 路由跳转错误处理
Router._errorHandler = function (e) {
  console.error(e);
};

Router.install = function (Vue) {
  Vue.mixin({
    onLaunch: function () {},
    onLoad: function (props) {
      // //传入VM应用数据
      // Router.$root.setAdhibition(this)
      // // 首次进入页面时,缓存中不存在当前路由信息，需要初始化路由信息
      // if (!Router.$root.getCurrentRoute()) {
      //     const rt = {
      //         params: {},
      //         path: '/' + getCurrentPages()[0].route
      //     }
      //     if (props) {
      //         Object.keys(props).forEach(k => {
      //             // url转的对象全部都是字符串，需要识别其中的对象和基本数据类型
      //             try {
      //                 const obj = JSON.parse(props[k])
      //                 if (typeof(obj) === 'string') {
      //                     // 只有字符串还会是字符串，数字、布尔、数组均会转换为正常类型
      //                     rt.params[k] = props[k]
      //                 } else {
      //                     rt.params[k] = obj
      //                 }
      //             } catch (e) {
      //                 rt.params[k] = props[k]
      //             }
      //         })
      //     }
      //     Router.$root.route = rt
      //     // 执行路由前置守卫
      //     Router.$root.doBeforeHooks()
      // }
    }
  });
  // //设置路由函数
  // Object.defineProperty(Vue.prototype, "$router", {
  //     get: function() {
  //         return Router.$root
  //     }
  // })
  // Object.defineProperty(Vue.prototype, "$route", {
  //     get: function() {
  //         return Router.$root.getCurrentRoute()
  //     }
  // })
};

export default Router;
